package com.first.wchat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.wchat.network.Actions;
import com.wchat.network.Configs;
import com.wchat.network.Controller;
import com.wchat.network.UserAction;
import com.wchat.network.device.Device;
import com.wchat.network.device.DeviceContext;
import com.wchat.network.device.Group;
import com.wchat.network.device.GroupParam;
import com.wchat.network.device.SendTarget;
import com.wchat.network.http.NanoHTTPD;
import com.wchat.network.message.Message;
import com.wchat.network.message.file.FileMessage;
import com.wchat.network.message.share.ShareItem;
import com.wchat.util.UserSettings;

public class TestActivity extends Activity {

	BroadcastReceiver receiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (Actions.ACTION_RECEIVE_MESSAGE.equals(action)) {
				Message message = (Message) intent.getSerializableExtra("message");
				Controller.getInstance().handle(message);
			} else if (Actions.ACTION_DEVICE_FOUND.equals(action)) {
				Device device = (Device) intent.getSerializableExtra("device");
				Configs.i("device found: " + device);
				bindData();
			} else if (Actions.ACTION_DEVICE_UPDATED.equals(action)) {
				Device device = (Device) intent.getSerializableExtra("device");
				Configs.i("device update: " + device);
				bindData();
			} else if (Actions.ACTION_DEVICE_LOST.equals(action)) {
				Device device = (Device) intent.getSerializableExtra("device");
				Configs.i("device lost: " + device);
				bindData();
			} else if (Actions.ACTION_GROUP_FOUND.equals(action)) {
				Group group = (Group) intent.getSerializableExtra("group");
				Configs.i("group found: " + group);
				bindData();
			} else if (Actions.ACTION_GROUP_UPDATED.equals(action)) {
				Group group = (Group) intent.getSerializableExtra("group");
				Configs.i("group updated: " + group);
				bindData();
			} else if (Actions.ACTION_GROUP_REMOVED.equals(action)) {
				Group group = (Group) intent.getSerializableExtra("group");
				Configs.i("group updated: " + group);
				bindData();
			} else if (Actions.ACTION_FILE_TRANSFER_START.equals(action)) {
				Toast.makeText(TestActivity.this, action + ": ", Toast.LENGTH_SHORT).show();
			} else if (Actions.ACTION_FILE_TRANSFER_PROGRESS.equals(action)) {
				Toast.makeText(TestActivity.this, action + ": ", Toast.LENGTH_SHORT).show();
			} else if (Actions.ACTION_FILE_TRANSFER_SUCCESS.equals(action)) {
				Toast.makeText(TestActivity.this, action + ": ", Toast.LENGTH_SHORT).show();
				FileMessage message = (FileMessage)intent.getSerializableExtra("message");
				File file = (File) intent.getSerializableExtra("file");
				if (message.getType() == Message.TYPE_IMAGE && file != null) {
					AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
					ImageView view = new ImageView(TestActivity.this);
					Drawable drawable = Drawable.createFromPath(file.getAbsolutePath());
					view.setImageDrawable(drawable);
					builder.setView(view);
					builder.show();
				}
			} else if (Actions.ACTION_FILE_TRANSFER_CANCELLED.equals(action)) {
				Toast.makeText(TestActivity.this, action + ": ", Toast.LENGTH_SHORT).show();
			} else if (Actions.ACTION_FILE_TRANSFER_FAILED.equals(action)) {
				Toast.makeText(TestActivity.this, action + ": ", Toast.LENGTH_SHORT).show();
			}

		}
	};

	UserAction userAction;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.testlayout);
		String name = UserSettings.getSettingString(this, UserSettings.Keys.USER_NAME);
		if (name == null || "".equals(name)) {
			showInputName();
		} else {
			init();
		}

		IntentFilter filter = new IntentFilter();
		filter.addAction(Actions.ACTION_RECEIVE_MESSAGE);
		filter.addAction(Actions.ACTION_DEVICE_FOUND);
		filter.addAction(Actions.ACTION_DEVICE_UPDATED);
		filter.addAction(Actions.ACTION_DEVICE_LOST);
		filter.addAction(Actions.ACTION_GROUP_FOUND);
		filter.addAction(Actions.ACTION_GROUP_UPDATED);
		filter.addAction(Actions.ACTION_GROUP_REMOVED);
		filter.addAction(Actions.ACTION_FILE_TRANSFER_START);
		filter.addAction(Actions.ACTION_FILE_TRANSFER_PROGRESS);
		filter.addAction(Actions.ACTION_FILE_TRANSFER_SUCCESS);
		filter.addAction(Actions.ACTION_FILE_TRANSFER_CANCELLED);
		filter.addAction(Actions.ACTION_FILE_TRANSFER_FAILED);
		registerReceiver(receiver, filter);

		Controller.getInstance().addShare(ShareItem.createShareItem(new File(Environment.getExternalStorageDirectory(), "test.png")));
		Controller.getInstance().addShare(ShareItem.createShareItem(new File(Environment.getExternalStorageDirectory(), "test2.png")));
		
		NanoHTTPD.main(null);
	}

	private void init() {
		userAction = Controller.getInstance();
		Controller.getInstance().start(this);
	}

	private void showInputName() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		View view = View.inflate(this, R.layout.promote_name, null);
		final EditText namEditText = (EditText) view.findViewById(R.id.input_name);
		builder.setView(view);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				String name = namEditText.getEditableText().toString();
				UserSettings.putSettingString(TestActivity.this, UserSettings.Keys.USER_NAME, name);
				UserSettings.putSettingLong(TestActivity.this, UserSettings.Keys.ID, Configs.generateUniqueDeviceId());
				init();
			}
		});
		builder.setNegativeButton("Cancel", null);
		builder.show();
	}

	@Override
	protected void onDestroy() {
		unregisterReceiver(receiver);
		Controller.getInstance().stop();
		super.onDestroy();
	}

	private void bindData() {
		ListView deviceListView = (ListView) findViewById(R.id.devices_listview);
		DeviceContext deviceContext = Controller.getInstance().getDeviceContext();
		final DeviceAdapter adapter = new DeviceAdapter(deviceContext.getDeviceList());
		deviceListView.setAdapter(adapter);
		deviceListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

				AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
				final SendTarget target = (SendTarget) adapter.getItem(position);
				CharSequence[] items = { "send message", "send file", "send image", "hand write message", "get share directory" };
				builder.setItems(items, new OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						if (which == 0) {
							showInputTextMessage(target);
						} else if (which == 1) {
							File file = new File(Environment.getExternalStorageDirectory(), "test.png");
							userAction.sendFile(file, target);
						} else if (which == 2) {
							File file = new File(Environment.getExternalStorageDirectory(), "test.png");
							userAction.sendImage(file, target);
						} else if (which == 3) {
							showInputHandWriteDialog(target);
						} else if (which == 4) {
							try {
								target.sendMessage(Message.createGetShareDirectoryMessage());
								} catch (Exception e) {
									Log.e("", "", e);
								}
						}
					}
				});

				builder.show();

			}

		});

		View addgroup = findViewById(R.id.add_group);
		addgroup.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				showAddGroupDialog();
			}
		});

		final ExpandableListView groupListView = (ExpandableListView) findViewById(R.id.group_listview);
		final GroupAdapter groupAdapter = new GroupAdapter(deviceContext.getGroups());
		groupListView.setAdapter(groupAdapter);

		groupListView.setOnGroupClickListener(new OnGroupClickListener() {

			@Override
			public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
				groupListView.expandGroup(groupPosition);
				final Group group = (Group) groupAdapter.getGroup(groupPosition);
				AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
				CharSequence[] items = { "join", "leave", "send group message", "send group image" };
				builder.setItems(items, new OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						if (which == 0) {
							userAction.joinGroup(group);
						} else if (which == 1) {
							userAction.leaveGroup(group);
						} else if (which == 2) {
							showInputTextMessage(group);
						} else if (which == 3) {
							File file = new File(Environment.getExternalStorageDirectory(), "test.png");
							userAction.sendImage(file, group);
						}
					}
				});

				builder.show();

				return true;
			}
		});
	}

	private void showInputTextMessage(final SendTarget target) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		View view = View.inflate(this, R.layout.promote_name, null);
		final TextView label = (TextView) view.findViewById(R.id.input_label);
		label.setText("input message: ");
		final EditText namEditText = (EditText) view.findViewById(R.id.input_name);
		builder.setView(view);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				String text = namEditText.getEditableText().toString();
				userAction.sendText(text, target);
			}
		});
		builder.setNegativeButton("Cancel", null);
		builder.show();
	}

	private void showInputHandWriteDialog(final SendTarget target) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		View view = View.inflate(this, R.layout.hand_write_panel, null);
		final GestureOverlayView gestureOverlayView = (GestureOverlayView) view.findViewById(R.id.gestures);
		final ArrayList<Path> paths = new ArrayList<Path>();
		gestureOverlayView.addOnGesturePerformedListener(new OnGesturePerformedListener() {

			@Override
			public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
				paths.add(gesture.toPath());
			}
		});
		builder.setView(view);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				Bitmap bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
				Canvas canvas = new Canvas(bitmap);

				final Paint paint = new Paint();
				paint.setAntiAlias(true);
				paint.setDither(true);
				paint.setStyle(Paint.Style.STROKE);
				paint.setStrokeJoin(Paint.Join.ROUND);
				paint.setStrokeCap(Paint.Cap.ROUND);
				paint.setStrokeWidth(2);

				int pathcount = paths.size();
				for (int i = 0; i < pathcount; i++) {
					Path path = paths.get(i);
					canvas.drawPath(path, paint);
					canvas.drawRect(new RectF(0.1f, 0.1f, 0.9f, 0.9f), paint);
				}
				File external = Environment.getExternalStorageDirectory();
				File wchat = new File(external, "wchat");
				File tempHandWrite = new File(wchat, "handwrite");
				if (!tempHandWrite.exists())
					tempHandWrite.mkdirs();
				File tempfile = new File(tempHandWrite, System.currentTimeMillis() + ".png");
				OutputStream os = null;
				try {
					os = new FileOutputStream(tempfile);
					bitmap.compress(CompressFormat.PNG, 100, os);
					os.flush();
				} catch (Exception e) {
					// TODO: handle exception
				} finally {
					if (os != null)
						try {
							os.close();
						} catch (Exception e) {
							// TODO: handle exception
						}
					bitmap.recycle();
				}
				userAction.sendImage(tempfile, target);
			}
		});
		builder.setNegativeButton("Cancel", null);
		builder.show();
	}

	private void showAddGroupDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		View view = View.inflate(this, R.layout.promote_name, null);
		final TextView label = (TextView) view.findViewById(R.id.input_label);
		label.setText("input group name: ");
		final EditText namEditText = (EditText) view.findViewById(R.id.input_name);
		builder.setView(view);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				String text = namEditText.getEditableText().toString();
				GroupParam param = new GroupParam();
				param.name = text;
				userAction.createGroup(param);
			}
		});
		builder.setNegativeButton("Cancel", null);
		builder.show();
	}

	private class DeviceAdapter extends BaseAdapter {

		ArrayList<Device> devices;

		public DeviceAdapter(ArrayList<Device> devices) {
			super();
			this.devices = devices;
		}

		@Override
		public int getCount() {
			return devices.size();
		}

		@Override
		public Object getItem(int position) {
			return devices.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View contentView, ViewGroup parent) {
			TextView tv = (TextView) View.inflate(TestActivity.this, R.layout.testtv, null);
			Device device = (Device) getItem(position);
			tv.setText("[" + device.getAddress() + "] " + device.getName());
			return tv;
		}

	}

	private class GroupAdapter extends BaseExpandableListAdapter {

		ArrayList<Group> groups;

		public GroupAdapter(ArrayList<Group> groups) {
			super();
			this.groups = groups;
		}

		@Override
		public int getGroupCount() {
			return groups.size();
		}

		@Override
		public int getChildrenCount(int groupPosition) {
			return Controller.getInstance().getDeviceContext().getDevicesInGroup(groups.get(groupPosition).getGroupid()).size();
		}

		@Override
		public Object getGroup(int groupPosition) {
			return groups.get(groupPosition);
		}

		@Override
		public Object getChild(int groupPosition, int childPosition) {
			return Controller.getInstance().getDeviceContext().getDevicesInGroup(groups.get(groupPosition).getGroupid()).get(childPosition);
		}

		@Override
		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		@Override
		public long getChildId(int groupPosition, int childPosition) {
			return childPosition;
		}

		@Override
		public boolean hasStableIds() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
			TextView tv = (TextView) View.inflate(TestActivity.this, R.layout.testtv, null);
			Group group = (Group) getGroup(groupPosition);
			tv.setText("     " + group.getParam().name);
			return tv;
		}

		@Override
		public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
			TextView tv = (TextView) View.inflate(TestActivity.this, R.layout.testtv, null);
			Device device = (Device) getChild(groupPosition, childPosition);
			tv.setText("[" + device.getAddress() + "] " + device.getName());
			return tv;
		}

		@Override
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			// TODO Auto-generated method stub
			return false;
		}

	}

}